package ru.usu.gv.gui.behavior;

import ru.usu.gv.core.GraphCanvas;
import ru.usu.gv.gui.layout.fd.ForceDirectedLayout;
import ru.usu.gv.gui.layout.fd.ForceDirectedLayoutSettings;
import ru.usu.gv.uicomponents.UIEdge;
import ru.usu.gv.uicomponents.UIGraph;
import ru.usu.gv.uicomponents.UIVertex;

import javax.media.j3d.BoundingSphere;
import javax.vecmath.Point3d;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author spupyrev
 * 06.11.2009
 */
public class OfflineDynamicVisBehavior_FD extends DynamicVisBehavior
{
	public OfflineDynamicVisBehavior_FD(BoundingSphere bound)
	{
		super(bound);
	}

	@Override
	public void processStimulus(Enumeration arg0)
	{
		wakeupOn(w);

		System.out.println("Running offline dynamic force-directed layout");

		ForceDirectedLayoutSettings settings = createLayoutSettings();
		//extract all graphs and layout them
		UIGraph currentGraph = GraphCanvas.getInstance().getCurrentGraph();

		settings.setAttempts(1);
		Map<Integer, Map<Integer, Double>> edges = extractSlicedGraph(currentGraph);
		Map<Integer, Point3d> initialPositions = extractInitialPositions(currentGraph, edges);
		Map<Integer, Point3d> positions = new ForceDirectedLayout(settings).run(edges, new HashMap(), initialPositions);

		if (setCoordinates(currentGraph, positions))
			currentGraph.draw();
		else
			setEnable(false);
	}

	private Map<Integer, Map<Integer, Double>> extractSlicedGraph(UIGraph currentGraph)
	{
		List<Double> zz = new ArrayList();
		Map<Integer, Map<Integer, Double>> graphs = new HashMap();
		for (UIVertex v : currentGraph.getVertexes())
		{
			double z = v.getPosition().z;
			if (!zz.contains(z))
			{
				zz.add(z);
			}

			graphs.put(v.getVertex().getIndex(), new HashMap());
		}

		Collections.sort(zz);
		double z_sep = (zz.size() < 2 ? -1 : zz.get(1) - zz.get(0));
		for (UIEdge e : currentGraph.getEdges())
		{
			UIVertex v = e.getV1();
			UIVertex u = e.getV2();
			if (v.getPosition().z != u.getPosition().z)
			{
				//if (v.getLabel().equals(u.getLabel()) && Math.abs(v.getPosition().z - u.getPosition().z) == z_sep)
				if (v.getLabel().equals(u.getLabel()))
				{
					double factor = Math.abs(u.getPosition().z - v.getPosition().z) / z_sep;
					factor = 1.0 / factor;
					graphs.get(v.getVertex().getIndex()).put(u.getVertex().getIndex(), factor);
					graphs.get(u.getVertex().getIndex()).put(v.getVertex().getIndex(), factor);
				}

				continue;
			}

			graphs.get(v.getVertex().getIndex()).put(u.getVertex().getIndex(), 1.0);
			graphs.get(u.getVertex().getIndex()).put(v.getVertex().getIndex(), 1.0);
		}

		return graphs;
	}

}
